package net.towee.client.com.dashboard.presenter;

import net.towee.client.com.dashboard.DashBoard;
import net.towee.client.com.dashboard.GadgetPusher;
import net.towee.client.gadgets.GadgetInfo;
import net.towee.client.gadgets.GadgetPresenter;
import net.towee.client.gadgets.GadgetsHolder;
import net.towee.client.managers.DashBoardManager;
import net.towee.model.account.Board;
import net.towee.model.account.Gadget;
import net.towee.model.account.impl.GadgetImpl;

import com.google.common.base.Preconditions;
import com.google.gwt.event.logical.shared.HasOpenHandlers;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.inject.Inject;

public class GadgetPusherPresenter implements GadgetPusher, OpenHandler<GadgetInfo> {

	public interface Display extends IsWidget {
		/**
		 * Add available in interface gadget
		 * 
		 * @param g
		 */
		void addAvailableGadgets(GadgetInfo g, boolean installed);

		/**
		 * Events bus for handling add gadget events
		 * 
		 * @return
		 */
		HasOpenHandlers<GadgetInfo> getAddGadgetEvents();
		
		void showPusher();

		void onGadgedAttached();
	}

	// Inject
	private final Display display;
	private final DashBoardManager boardManager;
	private final DashBoard dashBoard;

	// Current mod gadget
	private Board currentBoard;

	@Inject
	public GadgetPusherPresenter(Display display, DashBoardManager boardManager, DashBoard dashBoard) {
		this.display = display;
		this.boardManager = boardManager;
		this.dashBoard = dashBoard;

		display.getAddGadgetEvents().addOpenHandler(this);
	}

	@Override
	public void go(HasWidgets container) {
		Preconditions.checkNotNull(currentBoard, "null board");
		display.showPusher();
	}

	@Override
	public void setBoard(Board b) {
		this.currentBoard = b;

		// Add available gadgets
		for (GadgetInfo g : GadgetsHolder.getGadgetsList())
			display.addAvailableGadgets(g, b.containsGadget(g.getCanonicalName()));
	}

	@Override
	public void onOpen(OpenEvent<GadgetInfo> event) {
		Preconditions.checkArgument(!currentBoard.containsGadget(event.getTarget().getCanonicalName()),
				"gadget already on the board");

		// Get GadgetInfo
		final GadgetInfo info = event.getTarget();

		// Attach gadget to board
		boardManager.attachGadgetToBoard(currentBoard.getId(), new GadgetImpl(info.getCanonicalName()),
				new AsyncCallback<Gadget>() {
					@Override
					public void onFailure(Throwable caught) {
					}

					@Override
					public void onSuccess(Gadget result) {
						display.onGadgedAttached();
						showGadget( result, info );
					}
				});
	}

	/**
	 * Show given gadget on the board
	 * @param result
	 */
	protected void showGadget(Gadget result, GadgetInfo info) {
		info.getGadgetContainer(result, currentBoard, new AsyncCallback<GadgetPresenter>(){
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(GadgetPresenter result) {
				dashBoard.showGadget(currentBoard, result, 0, 0);	
			}
		});
	}
}